package cn.com.zcode.core.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.log4j.Logger;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import cn.com.zcode.core.model.BaseModelSupport;

public class BaseMybatisDaoSupport extends SqlSessionDaoSupport implements BaseDao {
	private static final Logger logger = Logger.getLogger(BaseMybatisDaoSupport.class);
	
	public int update(String key, Map<String, Object> map) {
		 return this.getSqlSession().update(key,map);
	}
	
	public <M extends BaseModelSupport> M add(String key, M t) {
		this.generateUUID(t);
		this.getSqlSession().insert(key, t);
		return t;
	}
	
	public <M extends BaseModelSupport> M update(String key, M t) {
		if(t.getId()!=null){
			this.getSqlSession().update(key, t);
		}else{
			throw new RuntimeException("ID can not be null");
		}
		return t;
	}

	public <M extends BaseModelSupport> M get(String key, Object pro) {
		return this.getSqlSession().selectOne(key, pro);
	}
	public <M extends BaseModelSupport> List<M> list(String key) {
		return this.getSqlSession().selectList(key);
	}
	public <M extends BaseModelSupport> List<M> list(String key, Object pro) {
		return this.getSqlSession().selectList(key, pro);
	}

//	@Override
//	public <M extends BaseModelSupport> M save(M t) {
//		Class<?> zlass = t.getClass();
//		String tableName = getTableName(zlass);
//		List<ResultMapping> rml = this.getResultMapping(zlass);
//		List<String> colList = new ArrayList<String>();
//		List<Object> valList = new ArrayList<Object>();
//		this.generateUUID(t);
//		try {
//			if (rml != null) {
//				for (ResultMapping resultMapping : rml) {
//					String prod = resultMapping.getProperty();
//					String colum = resultMapping.getColumn();
//					colList.add(colum);
//					Map<?, ?> mm = BeanUtils.describe(t);
//					Object value = mm.get(prod);
//					valList.add(value);
//				}
//			} else {
//				Map<?, ?> mm = BeanUtils.describe(t);
//				for (Object object : mm.keySet()) {
//					Object value = mm.get(object);
//					colList.add(object + "");
//					valList.add(value);
//				}
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//			throw new RuntimeException("Exception throw during saving operation");
//		}
//
//		Map<String, Object> map = new HashMap<String, Object>();
//		map.put("vals", valList);
//		map.put("cols", colList);
//		map.put("tableName", tableName);
//		this.getSqlSession().insert("save", map);
//
//		return t;
//	}

//	public <M extends BaseModelSupport> M getById(Class<M> zlass, String id) {
//
//		String tableName = getTableName(zlass);
//		Map<String, Object> map = new HashMap<String, Object>();
//		map.put("id", id);
//		map.put("tableName", tableName);
//		Map<String, ?> obj = this.getSqlSession().selectOne("getById", map);
//		List<ResultMapping> rml = this.getResultMapping(zlass);
//		M m = this.cost(zlass, rml, obj);
//		return m;
//	}

//	public <M extends BaseModelSupport> List<M> listByProperty(Class<M> zlass, String pro, Object val) {
//		String tableName = getTableName(zlass);
//		List<ResultMapping> rml = this.getResultMapping(zlass);
//		String col = pro;
//		if (rml != null) {
//			try {
//				for (ResultMapping resultMapping : rml) {
//					String prod = resultMapping.getProperty();
//					String colum = resultMapping.getColumn();
//					if (pro.trim().equals(prod.trim())) {
//						col = colum;
//					}
//				}
//			} catch (Exception e) {
//				e.printStackTrace();
//				throw new RuntimeException("Exception throw during saving operation");
//			}
//		}
//		Map<String, Object> map = new HashMap<String, Object>();
//		map.put("tableName", tableName);
//		map.put("column", col);
//		map.put("value", val);
//		List<Map<String, ?>> list = this.getSqlSession().selectList("listByProperty", map);
//		List<M> result = cost(zlass, rml, list);
//		return result;
//	}

//	@Override
//	public <M extends BaseModelSupport> List<M> listAll(Class<M> zlass) {
//		Map<String, Object> map = new HashMap<String, Object>();
//		String tableName = this.getTableName(zlass);
//		map.put("tableName", tableName);
//		List<Map<String, ?>> list = this.getSqlSession().selectList("findAll", map);
//		List<ResultMapping> rml = this.getResultMapping(zlass);
//		List<M> result = cost(zlass, rml, list);
//		return result;
//	}

//	private List<ResultMapping> getResultMapping(Class<?> zlass) {
//		String id = zlass.getSimpleName();
//		Configuration config = this.getSqlSession().getConfiguration();
//		List<ResultMapping> rml = null;
//		try {
//			ResultMap rm = config.getResultMap(id);
//			rml = rm.getPropertyResultMappings();
//
//		} catch (Exception e1) {
//			logger.warn("exception throwed during getting result Mapping");
//		}
//		return rml;
//	}

	protected <M extends BaseModelSupport> List<M> cost(Class<M> zlass, List<ResultMapping> rml, List<Map<String, ?>> list) {
		List<M> result = new ArrayList<M>();
		try {
			for (Map<String, ?> m : list) {
				M obj = cost(zlass, rml, m);
				result.add(obj);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("Exception throw during findAll operation");
		}
		return result;
	}

	protected <M extends BaseModelSupport> M cost(Class<M> zlass, List<ResultMapping> rml, Map<String, ?> m) {
		try {
			M obj = zlass.newInstance();
			if (rml != null) {
				for (ResultMapping resultMapping : rml) {
					String prod = resultMapping.getProperty();
					String colum = resultMapping.getColumn();
					Object value = m.get(colum);
					BeanUtils.copyProperty(obj, prod, value);
				}
			} else {
				BeanUtils.copyProperties(obj, m);
			}
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("Exception throw during findAll operation");
		}
	}

//	protected String getTableName(Class<?> zlass) {
//		String tableName = null;
//		Table table = zlass.getAnnotation(Table.class);
//		if (table != null && (tableName = table.name()) != null) {
//			return tableName;
//		} else {
//			throw new RuntimeException("can not found the Table property");
//		}
//	}

	protected String generateUUID(BaseModelSupport model) {
		String id = model.getId();
		if (id == null || id.trim().isEmpty()) {
			id = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
			model.setId(id);
		}
		return id;
	}
}
